package com.snatch.snatchnd.zreocsrv;


import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import Ice.Current;

import com.alibaba.fastjson.JSON;
import com.snatch.common.vo.NodeManageInput;
import com.snatch.common.vo.NodeManageOutput;
import com.snatch.common.vo.NodeTaskInput;
import com.snatch.common.vo.NodeTaskOutput;
import com.snatch.snatchnd.service.AccountService;
import com.snatch.snatchnd.service.TaskService;
import com.snatch.snatchnd.zreocsrvi._NodeZreocSrvIDisp;
import com.thoughtworks.xstream.XStream;

@SuppressWarnings("serial")
@Component
public class NodeZreocSrv extends _NodeZreocSrvIDisp {
	/**
	 * 
	 */
	private XStream xs = new XStream();
	
	@Autowired
	AccountService accountManageService;
	
	@Autowired
	TaskService taskService;

	private Logger logger = Logger.getLogger(NodeZreocSrv.class);
	@Override
	public String nodeManage(String xmlStr, Current __current) {
		NodeManageOutput nodeManageOutput = new NodeManageOutput();
		try {
			NodeManageInput nodeManageInput = JSON.parseObject(xmlStr,NodeManageInput.class);
			String webCode = nodeManageInput.getWebCode();
			int operate = nodeManageInput.getOperate();
			logger.info(nodeManageInput.getOnlyCode() + "收到管理中心发送过来的" + (operate == 1 ? "启用" : "停用" ) + webCode+ "抓取项的命令.");
			if (operate == 1) {// 启用
					accountManageService.loginAccount(webCode);
					nodeManageOutput.setStatus(1);// 成功
					nodeManageOutput.setRemark("启用成功!");
			} else if (operate == 0) {// 停用
				
					nodeManageOutput.setStatus(1);// 成功
					nodeManageOutput.setRemark("停用成功!");
			}
		} catch (Exception e) {
			e.printStackTrace();
			nodeManageOutput.setStatus(0);// 失败
			nodeManageOutput.setRemark("数据格式不正确!");// 当失败的时候会填写失败原因
		}
		return JSON.toJSONString(nodeManageOutput);
	}
	
	
	
	@Override
	public String snatchTask(String xmlStr, Current __current) {
		NodeTaskOutput nodeTaskOutput = new NodeTaskOutput();
		long tiem = System.currentTimeMillis();
		try {
			NodeTaskInput nodeTaskInput = JSON.parseObject(xmlStr,NodeTaskInput.class);
			int status = taskService.snatchTask(nodeTaskInput);
			nodeTaskOutput.setStatus(status);
			nodeTaskOutput.setRemark("采集任务已到节点!");
			
		} catch (Exception e) {
			e.printStackTrace();
			nodeTaskOutput.setStatus(0);// 失败
			nodeTaskOutput.setRemark("数据格式不正确!");// 当失败的时候会填写失败原因
		}
		System.out.println("任务时间:"+(System.currentTimeMillis()-tiem));
		return JSON.toJSONString(nodeTaskOutput);
	}

	
	public String queryAccount(String xmlStr, Current __current){
		return null;
	}
	@Override
	public String validateCode(String xmlStr, Current __current) {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public String configModify(String xmlStr, Current __current) {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public String synCode(String xmlStr, Current __current) {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public String bak1(String xmlStr, Current __current) {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public String bak2(String xmlStr, Current __current) {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public String bak3(String xmlStr, Current __current) {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public String bak4(String xmlStr, Current __current) {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public String bak5(String xmlStr, Current __current) {
		// TODO Auto-generated method stub
		return null;
	}


	
/*	*//**
	 * 配置修改接口
	 *//*
	@Override
	public String configModify(String xmlStr, Current current) {
		ConfigModifyOutput configModifyOutput = new ConfigModifyOutput();
		try {
			xs.alias("Config", MoreAccountConfig.class);
			xs.alias("LoginThirdAccount", LoginThirdAccount.class);
			xs.alias("Proxy", Proxy.class);

			StringReader stringReader = new StringReader(xmlStr);
			MoreAccountConfig configModifyInput = new MoreAccountConfig();
			xs.fromXML(stringReader, configModifyInput);

			NodeRegisterInput nodeRegisterInput = SystemData.nodeConfigs;
			List<MoreAccountConfig> configs = nodeRegisterInput.getConfigs();
			for (MoreAccountConfig config : configs) {
				if (config.getThirdSystem().equals(configModifyInput.getThirdSystem())) {
					if (config.getSnatchItem().equals(configModifyInput.getSnatchItem())) {
						BeanUtils.copyProperties(config, configModifyInput);// 复制两个不同类的对象的属性
					}
				}
			}
			ClassLoader loader = SystemMgr.class.getClassLoader();
			URL url = loader.getResource("com/sbf/node/cfg/snatchConfig.xml");
			PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(url.getFile()), "UTF-8"));// 创建一个PrintWriter对象，用于输出。
			xs.alias("NodeRegisterInput", NodeRegisterInput.class);
			xs.toXML(nodeRegisterInput, pw);// 在这里是输出到snatchConfig.xml中。这里的输出都是覆盖性的，不是末尾添加形式。

			SystemData.nodeConfigs = nodeRegisterInput;

			configModifyOutput.setStatus(1);// 成功
			configModifyOutput.setRemark("更新成功!");
		} catch (Exception e) {
			configModifyOutput.setStatus(0);// 失败
			configModifyOutput.setRemark("数据格式不正确");// 当失败的时候会填写失败原因
		}
		StringWriter sw = new StringWriter();
		xs.alias("ConfigModifyOutput", ConfigModifyOutput.class);
		xs.toXML(configModifyOutput, sw);
		return sw.toString();
	}

	*//**
	 * 后台抓取中心管理接口
	 *//*
	@Override
	public String nodeManage(String xmlStr, Current current) {
		NodeManageOutput nodeManageOutput = new NodeManageOutput();
		try {
			StringReader stringReader = new StringReader(xmlStr);
			NodeManageInput nodeManageInput = new NodeManageInput();
			xs.alias("NodeManageInput", NodeManageInput.class);
			xs.fromXML(stringReader, nodeManageInput);

			String thirdSystem = nodeManageInput.getThirdSystem();// 第三方系统(皇冠,利记,沙巴)
			// 抓取项{足球.单式(沙巴单式分单双与让球盘/大小球/标准盘), 足球.滚球}
			String snatchItem = nodeManageInput.getSnatchItem();

			String itemID = SystemUtil.getItemID(thirdSystem, snatchItem);

			int operate = nodeManageInput.getOperate();
			
			logger.info(nodeManageInput.getOnlyCode() + "收到管理中心发送过来的" + (operate == 1 ? "启用" : "停用" ) + thirdSystem + "." + snatchItem + "抓取项的命令.");

			if (operate == 1) {// 启用
				synchronized (SystemData.snatchItemStatus) {
					if (null != SystemData.loginItemStatus.get(itemID)) {
						// 去对应主题订阅数据
						regSeq(itemID + "_seq");
						logger.info("抓取项" + itemID + "到主题" + (itemID + "_seq") + "订阅版本号成功!");
						nodeManageOutput.setStatus(1);
						nodeManageOutput.setItemID(itemID);
						nodeManageOutput.setRemark("启用成功!");
					} else {
						LoginThread loginThread = ThreadMgr.factoryMoreAccountLoginThread(thirdSystem, snatchItem);
						if (null != loginThread) {
							loginThread.start();
							int count = 0;

							while ((loginThread.success < 0) && (count++ < 90)) {
								SystemData.snatchItemStatus.wait(1000);// 休眠1秒钟
							}

							if (loginThread.success == 0) {// 登陆失败
								nodeManageOutput.setStatus(0);// 失败
								nodeManageOutput.setRemark(loginThread.remark);// 当失败的时候会填写失败原因
								if (null != loginThread) {
									loginThread.flag = false;
								}
							} else if (loginThread.success == -1) {// 启用失败
								nodeManageOutput.setStatus(0);// 失败
								nodeManageOutput.setRemark("启用失败!");// 当失败的时候会填写失败原因

								if (null != loginThread) {
									loginThread.flag = false;
								}
							} else {// 登陆成功
								SnatchThread snatchThread = ThreadMgr.factoryMoreAccountSnatchThread(thirdSystem, snatchItem, loginThread);
								if (null != snatchThread) {
									snatchThread.start();// 启动抓取线程
									SystemData.snatchItemStatus.put(itemID, snatchThread);
									// 去对应主题订阅数据
									regSeq(snatchThread.getItemID() + "_seq");
									logger.info("抓取项" + itemID + "到主题" + (snatchThread.getItemID() + "_seq") + "订阅版本号成功!");
								}
								SystemData.loginItemStatus.put(itemID, loginThread);
								nodeManageOutput.setStatus(1);// 成功
								nodeManageOutput.setItemID(itemID);
								nodeManageOutput.setRemark("启用成功!");
							}
						}
					}
				}
			} else if (operate == 0) {// 停用
				synchronized (SystemData.snatchItemStatus) {
					LoginThread loginThread = SystemData.loginItemStatus.get(itemID);
					if (null != loginThread) {
						SnatchThread snatchThread = SystemData.snatchItemStatus.get(itemID);
						if (null != snatchThread) {
							snatchThread.destroy();
							SystemData.snatchItemStatus.remove(itemID, snatchThread);
							// 取消JMS监听服务
							innerJmsClusterMgr.unregistClusterListener(snatchThread.getItemID() + "_seq");
						}
						loginThread.flag = false;
						SystemData.loginItemStatus.remove(itemID, loginThread);
					}
					nodeManageOutput.setStatus(1);// 成功
					nodeManageOutput.setItemID(itemID);
					nodeManageOutput.setRemark("停用成功!");
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			nodeManageOutput.setStatus(0);// 失败
			nodeManageOutput.setRemark("数据格式不正确!");// 当失败的时候会填写失败原因
		}
		StringWriter sw = new StringWriter();
		xs.alias("NodeManageOutput", NodeManageOutput.class);
		xs.toXML(nodeManageOutput, sw);
		return sw.toString();
	}

	// 动态版本号订阅
	private void regSeq(String destName) {
		// 先解除原来可能的注册
		try {
			innerJmsClusterMgr.unregistClusterListener(destName);
		} catch (Exception e) {
		}
		// 再重新注册
		innerJmsClusterMgr.registClusterTopicListener(destName, new MessageListener() {
			@Override
			public void onMessage(Message message) {
				String itemID = "";
				long seqNum = 0;
				try {
					ObjectMessage mapMsg = (ObjectMessage) message;
					Map map = (HashMap) mapMsg.getObject();
					itemID = (String) map.get("item_id");
					seqNum = (Long) map.get("seq_num");
					
					//采用内存队列的消息无阻赛接收
					SystemData.SnatchItemQueueBean snatchItemQueueBean = SystemData.snatchItemSeqStackMap.get(itemID);
					if (null == snatchItemQueueBean) {
						snatchItemQueueBean = new SystemData.SnatchItemQueueBean();
						snatchItemQueueBean.snatchItemSeqStack = new LinkedList<Map<String, Object>>();
						snatchItemQueueBean.snatchItemSeqConsumer = new SeqQueueConsumer(snatchItemQueueBean.snatchItemSeqStack, itemID);
						snatchItemQueueBean.snatchItemSeqConsumer.start();
						SystemData.snatchItemSeqStackMap.put(itemID, snatchItemQueueBean);
					}
					synchronized (snatchItemQueueBean.snatchItemSeqStack) {
						snatchItemQueueBean.snatchItemSeqStack.add(map);
						snatchItemQueueBean.snatchItemSeqStack.notifyAll();
					}
				} catch (Exception e) {
					logger.info(e.getMessage());
				} finally {
					// 发送消息回执
					try {
						message.acknowledge();
						logger.info(itemID + "," + seqNum + "发送消息回执.");
					} catch (JMSException e) {
						logger.info(itemID + "," + seqNum + "发送消息回执出现异常!" + e.toString());
						// e.printStackTrace();
					}
				}
			}
		});
	}

	
	 * 内存版本号队列消费线程
	 
	class SeqQueueConsumer extends Thread {
		private LinkedList<Map<String, Object>> snatchItemSeqStack;
		private String itemID;

		public SeqQueueConsumer(LinkedList<Map<String, Object>> snatchItemSeqStack, String itemID) {
			this.snatchItemSeqStack = snatchItemSeqStack;
			this.itemID = itemID;
		}

		@Override
		public void run() {
			Map<String, Object> hm = null;
			long seqNum = 0;
			while (true) {
				try {
					synchronized (snatchItemSeqStack) {
						if (!snatchItemSeqStack.isEmpty()) {
							// 只使用最近发送的版本号
							hm = snatchItemSeqStack.getLast();
							seqNum = (Long) hm.get("seq_num");
							// 根据itemID控制不同抓取项线程的行为。
							SnatchThread snatchThread = SystemData.snatchItemStatus.get(itemID);
							// 该抓取节点有指定抓取项，并且对应的抓取线程处于空闲状态
							// if (null != snatchThread && !snatchThread.getSnatchStatus()) {
							// 该抓取节点有指定抓取项
							if (null != snatchThread) {
								logger.info("JMS收到" + itemID + "的版本号为:" + seqNum);
								snatchThread.setSeqNum(seqNum);
								snatchThread.snatchOpen();
							} else {
								logger.info("JMS收到" + itemID + "的版本号为:" + seqNum + ",并废弃!");
							}
							// 废弃过期的版本号
							snatchItemSeqStack.clear();
						} else {
							snatchItemSeqStack.wait(1000L);
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
					logger.error(itemID + "的版本号消费线程出现异常，" + e.toString());
				}
			}
		}
	}

	*//**
	 * 验证码接口
	 *//*
	@Override
	public String validateCode(String xmlStr, Current current) {
		// ValidateCodeOutput validateCodeOutput = new ValidateCodeOutput();
		// try {
		// StringReader stringReader = new StringReader(xmlStr);
		// ValidateCodeInput validateCodeInput = new ValidateCodeInput();
		// xs.alias("ValidateCodeInput", ValidateCodeInput.class);
		// xs.fromXML(stringReader, validateCodeInput);
		//
		// String thirdSystem = validateCodeInput.getThirdSystem();//
		// 第三方系统(皇冠,利记,沙巴)
		// // 抓取项{足球.单式(沙巴单式分单双与让球盘/大小球/标准盘), 足球.滚球}
		// String snatchItem = validateCodeInput.getSnatchItem();
		//
		// AbstractSnatchThread thread =
		// SystemData.snatchItemStatus.get(thirdSystem + "_" + snatchItem);//
		// 获取对应抓取项的线程
		// thread.setValidateCodeData(validateCodeInput.getData());
		// while (!thread.getSuccess()) {
		// Thread.sleep(1000);// 休眠1秒钟
		// }
		// if (thread.getValidateCode().equals("")) {
		// validateCodeOutput.setStatus(1);// 成功
		// } else {
		// validateCodeOutput.setStatus(2);// 需要验证码
		// validateCodeOutput.setImage(thread.getValidateCode());// 验证码图片字节流
		// }
		// } catch (Exception e) {
		// validateCodeOutput.setStatus(0);// 失败
		// validateCodeOutput.setRemark("数据格式不正确");// 当失败的时候会填写失败原因
		// }
		// StringWriter sw = new StringWriter();
		// xs.alias("ValidateCodeOutput", ValidateCodeOutput.class);
		// xs.toXML(validateCodeOutput, sw);
		// return sw.toString();
		return null;
	}

	@Override
	public String bak1(String xmlStr, Current current) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String bak2(String xmlStr, Current current) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String bak3(String xmlStr, Current current) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String bak4(String xmlStr, Current current) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String bak5(String xmlStr, Current current) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String synCode(String xmlStr, Current current) {
		
		return null;
	}*/
}
